<?php

namespace Laravel\ModulesGenerator;

require_once __DIR__ . '/Generator/Lib/Mongo.php';
require_once __DIR__ . '/Generator/Lib/MySQL.php';
require_once __DIR__ . '/Generator/Lib/Helper.php';

use Laravel\ModulesGenerator\Generator\Lib\Helper;
use Laravel\ModulesGenerator\Generator\Lib\Mongo;
use Laravel\ModulesGenerator\Generator\Lib\MySQL;
use Illuminate\Console\Command;

class Module extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'make:module';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate Model AND Controller';

    /**
     * 表名称
     *
     * @var
     */
    protected $table;

    /**
     * 数据库类型
     *
     * @var
     */
    protected $dbType;

    /**
     * 作者名
     *
     * @var
     */
    protected $author = '';

    protected $className;

    protected $classPath;

    protected $controllerName;

    protected $columns;

    protected $modelTemplate;

    protected $tableComment;

    protected $libObject = NULL;

    protected $helperObject = NULL;

    protected $currentDate;

    protected $casts = NULL;

    protected $modelPath;

    protected $validatorPath;

    protected $bllPath;

    protected $bllTemplate;

    protected $namespace;

    /**
     * Controller路径
     *
     * @var string
     */
    protected $controllerPath;

    //controlle file
    protected $controllTemplate;

    protected $validatorTemplate;

    /**
     * Create a new command instance.
     *
     * ModuleMake constructor.
     */
    public function __construct()
    {
        parent::__construct();

        $this->controllerPath = base_path() . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'Http' . DIRECTORY_SEPARATOR . 'Controllers' . DIRECTORY_SEPARATOR;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $table = $this->ask('Please Input The Table Name?');
        if ($table) {
            $this->table = $table;
        } else {
            throw new \RuntimeException('table can\'t be null');
        }
        $this->dbType = 'mysql';
        $dbType = $this->ask('Please Input The DB Type: mysql or mongo ?');
        if ($dbType) {
            $this->dbType = $dbType;
        } else {
            throw new \RuntimeException('dbType can\'t be null');
        }

        $author = $this->ask('Please Input The Author Name?');
        if ($author) {
            $this->author = $author;
        }

        $this->helperObject = new Helper();
        $info = $this->helperObject->preName($table);

        $this->table = $info['table'];
        $this->className = $info['className'];
        $this->classPath = $info['classPath'];
        $this->controllerName = $info['controllerName'];
        $this->currentDate = date("Y-m-d H:i:s");
        $this->namespace = $info['namespace'];

        $this->getLibObject();

        //获取表与字段信息
        $this->getTableComment();
        $this->getColumns();

        $this->getCasts();

        //生成Model
        $this->genModel();

        //生成Controller
        $this->genController();

        //生成Validator
        $this->genValidator();

        $this->line('Congratulations! All Files has generated!');

    }

    private function getLibObject()
    {
        if (strtolower($this->dbType) == 'mysql') {
            $this->libObject = new MySQL($this->table);
            $this->modelPath = base_path('app/Models/MySQL/');
            $this->modelTemplate = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Generator/Templates/MysqlModel.tpl');
            $this->controllTemplate = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . '/Generator/Templates/MysqlController.tpl');
        } elseif (strtolower($this->dbType) == 'mongo') {
            $this->libObject = new Mongo($this->className);
            $this->modelTemplate = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Generator/Templates/MongoModel.tpl');
            $this->modelPath = base_path('app/Models/Mongo/');
            $this->controllTemplate = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Generator/Templates/MongoController.tpl');
        }

        $this->validatorPath = base_path('app/Library/Validators/');
        $this->validatorTemplate = \file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Generator/Templates/Validator.tpl');

        $this->bllPath = base_path('app/Bll/'); //业务逻辑层
        $this->bllTemplate = \file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Generator/Templates/MysqlBll.tpl');

        return $this;
    }

    /**
     * Get the value of a command argument.
     *
     * @param  string $key
     * @return string|array
     */
    public function argument($key = NULL)
    {
        if (is_null($key)) {
            return $this->input->getArguments();
        }

        return $this->input->getArgument($key);
    }

    /**
     * Get the value of a command option.
     *
     * @param  string $key
     * @return string|array
     */
    public function option($key = NULL)
    {
        if (is_null($key)) {
            return $this->input->getOptions();
        }

        return $this->input->getOption($key);
    }

    /**
     * @param table
     *
     * Get table comment
     */
    protected function getTableComment()
    {
        $this->tableComment = $this->libObject->getTableComment();

        $this->line("Get table comment success.");
    }

    /**
     * get table columns
     *
     * @return void
     */
    protected function getColumns()
    {
        $this->columns = $this->libObject->getColumns();

        $this->line("Get table columns success.");
    }

    protected function getCasts()
    {
        $this->casts = $this->libObject->getCasts();

        $this->line("Get table casts success.");
    }

    /**
     * Model 生成
     * 以下是生成Model模板中所需变量
     * $className
     * $author
     * $currentDate
     * $table
     * $fields
     * $scopeFilterString
     */
    protected function genModel()
    {
        $_fields = array_keys($this->columns);
        $fillAbleFields = $this->helperObject->preFields($_fields);
        $casts = var_export($this->casts, TRUE);
        $casts = str_replace('array (', '[', $casts);
        $casts = str_replace(')', ']', $casts);

        $scopeFilterString = $this->helperObject->generateScopeFilter($_fields);
        $modelFileName = $this->className . '.php';
        $generateStatus = TRUE;
        $this->genParentDir($this->modelPath); //生成父级，文件夹

        $filePath = $this->modelPath . $this->classPath . $modelFileName;

        if (file_exists($filePath)) {
            $this->line("Model: " . $filePath . " is exist~");
            $replaceConfirm = $this->confirm('Do you want to replace it?');
            $generateStatus = $replaceConfirm;
        }

        if ($generateStatus) {
            $modelContent = str_replace(['{$className}', '{$tableComment}', '{$author}', '{$currentDate}', '{$table}',
                '{$fields}', '{$casts}', '{$scopeFilterString}', '{namespace}'],
                [$this->className, $this->tableComment, $this->author, $this->currentDate, $this->table, $fillAbleFields,
                    $casts, $scopeFilterString, $this->namespace],
                $this->modelTemplate);

            file_put_contents($filePath, $modelContent);
            $this->line("Model: " . $filePath . " has generator success~");
        }

        $this->line("Thank U~");
    }


    /**
     * Bll 生成 业务逻辑层
     * 以下是生成Model模板中所需变量
     * $className
     * $author
     * $currentDate
     * $table
     * $fields
     * $scopeFilterString
     */
    protected function genBll()
    {
        $_fields = array_keys($this->columns);
        /*$fillAbleFields = $this->helperObject->preFields($_fields);
        $casts = var_export($this->casts, TRUE);
        $casts = str_replace('array (', '[', $casts);
        $casts = str_replace(')', ']', $casts);*/

        $scopeFilterString = $this->helperObject->generateScopeFilter($_fields);
        $modelFileName = $this->className . '.php';
        $generateStatus = TRUE;
        $this->genParentDir($this->modelPath); //生成父级，文件夹

        $filePath = $this->bllPath . $this->classPath . $modelFileName;

        if (file_exists($filePath)) {
            $this->line("Model: " . $filePath . " is exist~");
            $replaceConfirm = $this->confirm('Do you want to replace it?');
            $generateStatus = $replaceConfirm;
        }

        if ($generateStatus) {
            $modelContent = str_replace(['{$className}', '{$tableComment}', '{$author}', '{$currentDate}', '{$table}', '{$scopeFilterString}'],
                [$this->className, $this->tableComment, $this->author, $this->currentDate, $this->table, $scopeFilterString],
                $this->bllTemplate);

            file_put_contents($filePath, $modelContent);
            $this->line("Model: " . $filePath . " has generator success~");
        }

        $this->line("Thank U~");
    }

    /**
     * Controller 生成
     */
    protected function genController()
    {
        $controllerFileName = $this->className . 'Controller.php';
        $generateStatus = TRUE;

        $filePath = $this->controllerPath . $this->classPath . $this->controllerName . '.php';
        $this->genParentDir($this->controllerPath); //生成父级，文件夹

        if (file_exists($filePath)) {
            $this->line("Controller: " . $filePath . " is exist~");
            $replaceConfirm = $this->confirm('Do you want to replace it?');
            $generateStatus = $replaceConfirm;
        }

        $tableName = app('config')->get('database.connections.mongodb.prefix') . $this->table;

        if ($generateStatus) {
            $modelContent = str_replace(['{$className}', '{$controllerName}', '{$table}', '{$author}', '{$currentDate}', '{namespace}'],
                [$this->className, $this->className . 'Controller', $tableName, $this->author, $this->currentDate, $this->namespace],
                $this->controllTemplate);

            file_put_contents($filePath, $modelContent);
            $this->line("Controller: " . $filePath . " has generator success~");
        }

    }

    /**
     * Validator 生成
     */
    protected function genValidator()
    {
        $fileName = $this->className . 'Validator.php';
        $generateStatus = TRUE;

        $this->genParentDir($this->validatorPath); //生成父级，文件夹
        $filePath = $this->validatorPath . $this->classPath . $fileName;

        if (file_exists($filePath)) {
            $this->line("Validator: " . $filePath . " is exist~");
            $replaceConfirm = $this->confirm('Do you want to replace it?');
            $generateStatus = $replaceConfirm;
        }

        if ($generateStatus) {
            $content = str_replace(['{$className}', '{$author}', '{$currentDate}', '{namespace}'],
                [$this->className, $this->author, $this->currentDate, $this->namespace],
                $this->validatorTemplate);

            file_put_contents($filePath, $content);
            $this->line("Validator: " . $filePath . " has generator success~");
        }

    }

    /**
     * 生成父级文件夹
     *
     * @param $basePath
     */
    protected function genParentDir($basePath)
    {
        $arr = explode(DIRECTORY_SEPARATOR, $this->classPath);
        $count = count($arr);

        if ($count > 1) {
            foreach ($arr as $key => $val) {
                $path = $basePath . $val . DIRECTORY_SEPARATOR;
                if (!is_dir($path)) {
                    mkdir($path,0777,true);
                }
                $basePath = $path;
            }
        }
    }
}
